home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 118 / MacAddict 118 2006-06.toast / Software / Development / REALbasic 2006 (demo).dmg / .Trashes / 501 / Locking Mechanisms.txt < prev    next >
Text File  |  2005-05-18  |  7KB  |  37 lines

  1. Locking Mechanisms.txt
  2. by Aaron Ballman
  3.  
  4. Locking mechanisms is the general term to describe the three ways to protect sections of code in a multithreaded environment.  You can protect code with a Semaphore, a Critical Section or a Mutex.  In RB 6.0, all of the locking mechanisms have been overhauled (and a new one added with the Mutex class), so this document will describe what each class is and how they work.
  5.  
  6. Semaphores
  7. The Semaphore class is a way for you to protect multiple related resources with a single object.  For example, you may have a limited number of objects that you can "pass around" to requesting threads.  A non-computing example would be that you have 10 pencils that you can give out.  Each person requests a pencil, and if there's one available, the semaphore will give it out.  If there are no pencils left, the person is left waiting in line until a pencil is available.  Pencils become available by being released by a person who's borrowed it.
  8.  
  9. Semaphore.Constructor( initialCount as Integer ) -- The Semaphore class has a Constructor that takes a single parameter -- the number of resources the semaphore is meant to protect.  This parameter defaults to 1 for backwards compatibility, tho if you only have one resource to protect, there are better ways to do it.
  10.  
  11. Semaphore.Signal() -- This is the way that you obtain a lock on a resource.  For example, calling Signal is akin to asking for a pencil.  If you are able to get the lock, this function returns immediately.  If the lock is not available, then the thread which called this function will block until the lock becomes available (like waiting in line for someone to return a pencil).  Just understand that once the call to Signal returns, you will have the lock on the resource (you may have waited for that lock though).  One thing to keep in mind is that each call to Signal will take another resource.  This means that you cannot have the same thread call Signal multiple times unless there are resources available.
  12.  
  13. Semaphore.TrySignal() as Boolean -- this is a more friendly version if Signal in that it gives you a sneak-peek to determine whether there is a lock available.  If there is a lock available, you are granted the lock and the function returns true.  If there isn't one ready for you, you do NOT block.  Instead, this function returns false to let you know.  If you haven't been given the lock, then you had better not try to use the resource!
  14.  
  15. Semaphore.Release() -- this is the way you give a resource back to the Semaphore.  It's just like handing the pencil back in our example.  Every time you call Signal (or succesfully call TrySignal), you must call Release.
  16.  
  17. Every time you succesfully obtain a lock on the resource, the Semaphore will decrement it's internal count of available resources.  When there aren't any more left is when threads will begin to block and wait for resources.  This is why you are allowed to pass in the initial count of resources -- to give you more control over the behavior of the semaphore.
  18.  
  19. CriticalSection
  20. The CriticalSection class is a way for you to protect a single resource.  For example, you may have one thread writing to a file, and another thread reading from the same file.  In this case, the resource they both share is the file, and you need to protect it, otherwise the file can get into a messed up state.  CriticalSections should be used when trying to safeguard a single resource.  They will behave the same way as a Semaphore with an initialCount of 1 in that there is only one resource to protect.
  21.  
  22. CriticalSection.Enter() -- This function behaves the same as Semaphore.Signal in that it attempts to get a lock on the single resource.  Once the lock is obtained, this function returns.  If the lock cannot be obtained immediately, then this method will block the current thread from running.  One way in which this method is different from Semaphore.Signal is in the fact that the currently executing thread can call Enter multiple times.  With Semaphore.Signal, every time the method is called, a resource is grabbed.  It doesn't matter which thread calls it.  With CriticalSection.Enter, if the calling thread already owns the lock, the method returns immediately.  This makes CriticalSections very useful for calling a method recursively.
  23.  
  24. CriticalSection.TryEnter() -- TryEnter behaves in much the same way as Enter does.  The only difference is that if the lock cannot be obtained, the method does not cause the current thread to block -- instead it returns false.  If the lock can be obtained, the function returns true.
  25.  
  26. CriticalSection.Leave() -- This function is the way you give a resource back.  Every time you call Enter or TryEnter and succeed (this includes recursively calling it), you must call Leave, otherwise the resource will stay protected forever.
  27.  
  28. Mutex
  29. A Mutex is a special type of CriticalSection with one very important difference: a CriticalSection has application-wide authority, but a Mutex has system-wide authority.  That means that a mutex created in Application A can be seen and referenced by a mutex created in Application B.  Aside from that, the way a Mutex behaves is identical to a CriticalSection.  Mutexes can be named (which makes them system-wide), or unmamed (which makes them application-wide, basically a CriticalSection).
  30.  
  31. You may be wondering how these can be used.  Well, the most common use for a Mutex is to determine whether another instance of your application is currently running or not.  If you make a named Mutex in the application's open event, then check to see if you can get a lock on it, but the lock fails, then you know there's another instance of your application running somewhere.  You can also use Mutexes to work with resources that are shared between applications (such as a serial port, printer, or some other system device).
  32.  
  33. Note that RB provides its own cross-platform Mutex class by using lock files in the user's temporary folder.  This means that you cannot use an RB mutex with another type of system mutex (such as the Win32 Mutex APIs or the POSIX named semaphore APIs).
  34.  
  35. Mutext.Constructor( name as String ) -- The constructor allows you to pick a name for the Mutex.  If you pass in an empty string, the mutex will behave identical to a critical section (the object will not be accessible by other applications).  If you pass in a string, that's the mutex's name, so other applications can access the mutex.
  36.  
  37. All of the other Mutex functions are the same as the CriticalSection functions.  The same rules apply to both classes: You can re-enter a Mutex in the same way as a CriticalSection, and the blocking mechanisms all happen the same as well.